
package com.hlkj.pay.app.merchant.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.LocalContext;
import com.hlkj.framework.common.util.id.IdUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.IMerchantConfigAppService;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.common.MerchantResultCode;
import com.hlkj.pay.dto.merchant.MerchantLimitPaymentDto;
import com.hlkj.pay.dto.merchant.config.MerchantPaymentConfigDto;
import com.hlkj.pay.dto.merchant.config.MerchantPaymentConfigMappingDto;
import com.hlkj.pay.dto.merchant.config.MerchantReportConfigDto;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantConfigDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantInfoDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantPaymentAccountConfigDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantPaymentConfigMappingDO;
import com.hlkj.pay.service.common.IOperatedLogService;
import com.hlkj.pay.service.merchant.IMerchantConfigService;
import com.hlkj.pay.service.merchant.IMerchantService;
import com.hlkj.pay.util.MerchantUtils;
import com.hlkj.pay.vo.merchant.req.config.MerchantLimitConfigReq;
import com.hlkj.pay.vo.merchant.req.config.MerchantPaymentAccountConfigReq;
import com.hlkj.pay.vo.merchant.req.config.MerchantPaymentConfigReq;
import com.hlkj.pay.vo.merchant.req.config.MerchantReportConfigReq;
import com.hlkj.pay.vo.merchant.req.report.MerchantPaymentConfigMappingReq;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;

/**
 * @author HlpayTeam
 * @date 2024/12/18 13:48
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MerchantConfigAppServiceImpl implements IMerchantConfigAppService {

    private final IMerchantConfigService merchantConfigService;

    private final IOperatedLogService merchantLogService;

    private final IMerchantService merchantService;

    @Override
    public CommonResult<Void> paymentConfig(MerchantPaymentConfigReq merchantPaymentConfigReq) {
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantPaymentConfigReq.getSn());
        if (merchantConfigDO == null) {
            merchantConfigDO = new MerchantConfigDO();
        }
        MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(merchantConfigDO.getSn());
        if (merchantConfigDO.getId() == null) {
            merchantConfigDO.setPaymentConfig(JsonUtils.toJsonString(merchantPaymentConfigReq));
            merchantConfigDO.setSn(merchantPaymentConfigReq.getSn());
            merchantConfigService.saveConfig(merchantConfigDO);
        }
        else {
            MerchantConfigDO update = new MerchantConfigDO();
            update.setId(merchantConfigDO.getId());
            update.setPaymentConfig(JsonUtils.toJsonString(merchantPaymentConfigReq));
            update.setSn(merchantConfigDO.getSn());
            merchantConfigService.updateConfig(update);
        }
        if (merchantPaymentConfigReq.getStatus() == 1) {
            merchantLogService.save(merchantInfoDO.getId(), MerchantEnum.MERCHANT_LOG_TYPE.MERCHANT, "开启代付", "商户开启代付配置");
        } else {
            merchantLogService.save(merchantInfoDO.getId(), MerchantEnum.MERCHANT_LOG_TYPE.MERCHANT, "关闭代付", "商户关闭代付配置");
        }
        return CommonResult.success();
    }

    @Override
    public MerchantPaymentConfigDto queryPaymentConfig(String sn) {
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(sn);
        if (merchantConfigDO == null || !StringUtils.hasText(merchantConfigDO.getPaymentConfig())) {
            return null;
        }
        return JsonUtils.parseObject(merchantConfigDO.getPaymentConfig(), MerchantPaymentConfigDto.class);
    }

    @Override
    public CommonResult<Void> reportConfig(MerchantReportConfigReq merchantReportConfigReq) {
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantReportConfigReq.getSn());
        if (merchantConfigDO == null) {
            merchantConfigDO = new MerchantConfigDO();
        }
        MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(merchantConfigDO.getSn());
        if (merchantConfigDO.getId() == null) {
            merchantConfigDO.setReportConfig(JsonUtils.toJsonString(merchantReportConfigReq));
            merchantConfigDO.setSn(merchantReportConfigReq.getSn());
            merchantConfigService.saveConfig(merchantConfigDO);
        }
        else {
            MerchantConfigDO update = new MerchantConfigDO();
            update.setId(merchantConfigDO.getId());
            update.setReportConfig(JsonUtils.toJsonString(merchantReportConfigReq));
            update.setSn(merchantConfigDO.getSn());
            merchantConfigService.updateConfig(update);
        }
        if (merchantReportConfigReq.getStatus() == 1) {
            merchantLogService.save(merchantInfoDO.getId(), MerchantEnum.MERCHANT_LOG_TYPE.MERCHANT, "开启汇电通", "商户开启汇电通配置");
        } else {
            merchantLogService.save(merchantInfoDO.getId(), MerchantEnum.MERCHANT_LOG_TYPE.MERCHANT, "关闭汇电通", "商户关闭汇电通配置");
        }
        return CommonResult.success();
    }

    @Override
    public MerchantReportConfigDto queryReportConfig(String sn) {
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(sn);
        if (merchantConfigDO == null || !StringUtils.hasText(merchantConfigDO.getReportConfig())) {
            return null;
        }
        return JsonUtils.parseObject(merchantConfigDO.getReportConfig(), MerchantReportConfigDto.class);
    }

    @Override
    public CommonResult<Void> addMerchantPaymentAccountConfig(MerchantPaymentAccountConfigReq merchantPaymentAccountConfigReq) {
        log.info("addMerchantReportConfig merchantPaymentAccountConfigReq:{}", JsonUtils.toJsonString(merchantPaymentAccountConfigReq));
        try {
            MerchantPaymentAccountConfigDO queryConfig = merchantConfigService.queryPaymentAccountConfig(merchantPaymentAccountConfigReq.getCardNo());
            if (queryConfig != null) {
                return CommonResult.error(CommonResultCode.DATA_HAS_EXIST);
            }
            MerchantPaymentAccountConfigDO merchantPaymentAccountConfigDO = BeanUtil.copy(merchantPaymentAccountConfigReq, MerchantPaymentAccountConfigDO.class);
            merchantPaymentAccountConfigDO.setCode(IdUtils.getSnowflakeNextIdStr());
            merchantPaymentAccountConfigDO.setSn(LocalContext.get().getSn());
            merchantConfigService.addPaymentAccountConfig(merchantPaymentAccountConfigDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("addMerchantReportConfig error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> updateMerchantPaymentAccountConfig(MerchantPaymentAccountConfigReq merchantPaymentAccountConfigReq) {
        log.info("updateMerchantReportConfig merchantPaymentAccountConfigReq:{}", JsonUtils.toJsonString(merchantPaymentAccountConfigReq));
        try {
            MerchantPaymentAccountConfigDO queryConfig = merchantConfigService.queryPaymentAccountConfigByCode(merchantPaymentAccountConfigReq.getCode());
            if (queryConfig == null) {
                return CommonResult.error(CommonResultCode.DATA_NOT_EXIST);
            }
            MerchantPaymentAccountConfigDO merchantPaymentAccountConfigDO = BeanUtil.copy(merchantPaymentAccountConfigReq, MerchantPaymentAccountConfigDO.class);
            merchantPaymentAccountConfigDO.setId(queryConfig.getId());
            merchantConfigService.updatePaymentAccountConfig(merchantPaymentAccountConfigDO);
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("updateMerchantReportConfig error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> delMerchantPaymentAccountConfig(String code) {
        log.info("delMerchantReportConfig code:{}", code);
        try {
            MerchantPaymentAccountConfigDO queryConfig = merchantConfigService.queryPaymentAccountConfigByCode(code);
            if (queryConfig == null) {
                return CommonResult.error(CommonResultCode.DATA_NOT_EXIST);
            }
            merchantConfigService.delPaymentAccountConfig(queryConfig.getId());
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("delMerchantReportConfig error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> saveMerchantConfigMapping(MerchantPaymentConfigMappingReq merchantReportConfigPageReq) {
        log.info("saveMerchantConfigMapping merchantReportConfigPageReq:{}", JsonUtils.toJsonString(merchantReportConfigPageReq));
        try {
            if (!StringUtils.hasText(merchantReportConfigPageReq.getPayAmount())) {
                return CommonResult.error(CommonResultCode.PARAMETER_MISSING);
            }
            List<MerchantPaymentConfigMappingDto> configMappingDtos = merchantConfigService.queryConfigMappingList(merchantReportConfigPageReq.getRelationId(),
                    merchantReportConfigPageReq.getRelationType());
            MerchantPaymentConfigMappingDO merchantPaymentConfigMappingDO = merchantConfigService.queryConfigMapping(merchantReportConfigPageReq.getRelationId(),
                    merchantReportConfigPageReq.getRelationType(), merchantReportConfigPageReq.getAccountCode());
            BigDecimal bigDecimal = new BigDecimal(merchantReportConfigPageReq.getPayAmount());
            if (merchantPaymentConfigMappingDO != null) {
                if (!CollectionUtils.isEmpty(configMappingDtos)) {
                    double summed = configMappingDtos.stream().filter(configMapping -> !configMapping.getCode().equals(merchantReportConfigPageReq.getAccountCode()))
                            .mapToDouble(configMapping -> configMapping.getPayAmount().doubleValue()).sum();
                    if (MerchantUtils.add(new BigDecimal(summed), bigDecimal).compareTo(new BigDecimal(100)) > 0) {
                        return CommonResult.error(MerchantResultCode.REPORT_CONFIG_PAY_AMOUNT_ERROR);
                    }
                }
                // 保存
                merchantPaymentConfigMappingDO.setPayAmount(bigDecimal);
                merchantConfigService.updateMerchantReportConfig(merchantPaymentConfigMappingDO);
            }
            else {
                if (!CollectionUtils.isEmpty(configMappingDtos)) {
                    double summed = configMappingDtos.stream().mapToDouble(configMapping -> configMapping.getPayAmount().doubleValue()).sum();
                    if (MerchantUtils.add(new BigDecimal(summed), bigDecimal).compareTo(new BigDecimal(100)) > 0) {
                        return CommonResult.error(MerchantResultCode.REPORT_CONFIG_PAY_AMOUNT_ERROR);
                    }
                }
                merchantPaymentConfigMappingDO = new MerchantPaymentConfigMappingDO();
                merchantPaymentConfigMappingDO.setRelationId(merchantReportConfigPageReq.getRelationId());
                merchantPaymentConfigMappingDO.setRelationType(merchantReportConfigPageReq.getRelationType());
                merchantPaymentConfigMappingDO.setAccountCode(merchantReportConfigPageReq.getAccountCode());
                merchantPaymentConfigMappingDO.setPayAmount(bigDecimal);
                merchantConfigService.addMerchantReportConfig(merchantPaymentConfigMappingDO);
            }
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("updateMerchantReportConfig error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> delMerchantConfigMapping(MerchantPaymentConfigMappingReq merchantReportConfigPageReq) {
        log.info("saveMerchantConfigMapping delMerchantConfigMapping:{}", JsonUtils.toJsonString(merchantReportConfigPageReq));
        try {
            MerchantPaymentConfigMappingDO merchantPaymentConfigMappingDO = merchantConfigService.queryConfigMapping(merchantReportConfigPageReq.getRelationId(),
                    merchantReportConfigPageReq.getRelationType(), merchantReportConfigPageReq.getAccountCode());
            if (merchantPaymentConfigMappingDO == null) {
                CommonResult.error(CommonResultCode.DATA_NOT_EXIST);
            }
            merchantConfigService.delMerchantReportConfig(merchantPaymentConfigMappingDO.getId());
            return CommonResult.success();
        }
        catch (Exception e) {
            log.error("updateMerchantReportConfig error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<Void> limitConfig(MerchantLimitConfigReq merchantLimitConfigReq) {
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(merchantLimitConfigReq.getSn());
        if (merchantConfigDO == null) {
            merchantConfigDO = new MerchantConfigDO();
        }
        MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(merchantConfigDO.getSn());
        if (merchantConfigDO.getId() == null) {
            merchantConfigDO.setLimitConfig(JsonUtils.toJsonString(merchantLimitConfigReq));
            merchantConfigDO.setSn(merchantLimitConfigReq.getSn());
            merchantConfigService.saveConfig(merchantConfigDO);
        }
        else {
            MerchantConfigDO update = new MerchantConfigDO();
            update.setId(merchantConfigDO.getId());
            update.setLimitConfig(JsonUtils.toJsonString(merchantLimitConfigReq));
            update.setSn(merchantConfigDO.getSn());
            merchantConfigService.updateConfig(update);
        }
        if (merchantLimitConfigReq.getLimitState() == 1) {
            merchantLogService.save(merchantInfoDO.getId(), MerchantEnum.MERCHANT_LOG_TYPE.MERCHANT, "开启限额", "商户开启支付限额");
        } else {
            merchantLogService.save(merchantInfoDO.getId(), MerchantEnum.MERCHANT_LOG_TYPE.MERCHANT, "关闭限额", "商户关闭支付限额");
        }
        return CommonResult.success();
    }

    @Override
    public MerchantLimitPaymentDto queryLimitConfig(String sn) {
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(sn);
        if (merchantConfigDO == null || !StringUtils.hasText(merchantConfigDO.getLimitConfig())) {
            return null;
        }
        return JsonUtils.parseObject(merchantConfigDO.getLimitConfig(), MerchantLimitPaymentDto.class);
    }
}
